package com.fingard.dsp.bank.directbank.gzdsf01;

import cfbs.api.CFBSConstant;
import cfbs.api.CFBSMsgUtil;
import cfbs.model.CfbsPlMsg;
import cfbs.model.CfbsPlMsg.CfbsPlMsgDetail;
import com.fingard.constant.Format;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.directbank.gzdsf01.util.FtpUtil;
import com.fingard.dsp.bank.directbank.gzdsf01.util.JSONUtil;
import com.fingard.dsp.bank.helpers.SeqBatchInfo;
import com.fingard.dsp.bank.helpers.SeqBatchInfoHelper;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.text.StringHelper;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

import java.io.File;
import java.util.List;

/**
 * 广东代收付系统批量代收付
 * 
 * @author Cruise
 * @date 2019/3/11
 */
public class GZDSF01BatPayRec extends GZDSF01Base implements IBatPayRec {
	@Override
	public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
		return d_BatPayRec(p_req1988);
	}

	@Override
	public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
		return d_QryBatPayRec(p_req1998);
	}

	@Override
	public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
		return d_BatPayRec(p_req9188);
	}

	@Override
	public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
		return d_QryBatPayRec(p_req9198);
	}
	
	public RetAtsBatPayRec d_BatPayRec(ReqBatPayRec p_reqBat) throws Exception {
		RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_reqBat.reqHeader);
		retAts.reqSeqID = p_reqBat.reqBatchNO;

		FTPClient uploadFtpClient = null;
		SeqBatchInfoHelper seqBatHelper = null;
		
		try {
			// 文件名:文件类型 + 报文类型标识符 + 交易种类 + 渠道 + 机构代码 + 委托日期 + 批量包序号 + 文件长度
			String ftpLocalDirSend = getBankConfig().getValueAsFilePath("ftpLocalDirSend");
			File mdDir = new File(ftpLocalDirSend);
	        if (!mdDir.exists()) {
	            mdDir.mkdirs();
	        }
			String transType = "";
			if (p_reqBat.reqHeader.isBatRec) {
				transType = GZDSF01TransCode.BATREC;
			}else if (p_reqBat.reqHeader.isBatPay) {
				transType = GZDSF01TransCode.BATPAY;
			}
			seqBatHelper = new SeqBatchInfoHelper(p_reqBat.reqHeader.tenant, p_reqBat.getPayDateTime());
			SeqBatchInfo batInfo = new SeqBatchInfo();
			batInfo.loadFromReqBat(p_reqBat);
			//int batSeqNo = getBatSeqNo(ftpLocalDirSend);
			batInfo.batSeqNo = seqBatHelper.getNextBatSeq(batInfo);
			String tmpBatSeqNo = String.format("%8s", batInfo.batSeqNo).replace(" ", "0");
			//String pldsFileName = 
			batInfo.upFileName = "TXNTYP1202" + transType + "00" + bankFront.org + Format.Date8Format.format(p_reqBat.getPayDateTime()) + tmpBatSeqNo;
			
			// 批次流水映射存入本地
			//WriteBankLogLn("本地批次流水映射文件内容:" + tmpBatSeqNo);
			//String tmpSeqNoPath = getDataFileDirectory(p_reqBat.getPayDateTime()) + File.separator + p_reqBat.reqBatchNO + ".txt";
			//WriteBankLogLn2("本地批次流水映射文件路径:" + tmpSeqNoPath);
			//FileHelper.writeFile(tmpSeqNoPath, tmpBatSeqNo, getCharset());
			
			// 文件头部字段信息
			CfbsPlMsg pldsMsg = new CfbsPlMsg();
			pldsMsg.setFileName(batInfo.upFileName);
			pldsMsg.setOrgId(bankFront.org);//机构号
			pldsMsg.setOrigBank(getBankConfig().getMapValueByKey("bankBranchMapping", p_reqBat.ownAct));//发起方开户行行号
			pldsMsg.setOrigAcc(p_reqBat.ownAct);//发起方开户账号
			//pldsMsg.setOutBank(p_reqBat.cnapscode);//接收方代码
			//pldsMsg.setTranType("00600");//业务种类
			pldsMsg.setMsgType("1202");
			pldsMsg.setCurrency("CNY");
			pldsMsg.setTotalCount(p_reqBat.totalNum);
			pldsMsg.setTotalAmount(StringHelper.amountMultiply100(p_reqBat.totalAmt));

			if (!p_reqBat.reqHeader.isBatRec) {
				String payContractNo = getBankConfig().getMapValueByKey("contractNoMapping", p_reqBat.ownAct);
				payContractNo = CFBSMsgUtil.rightFill(CFBSConstant.FILL_WORD_BLANK_SPACE, 60, payContractNo);
				pldsMsg.setCustomLength(payContractNo.length() + "");
				pldsMsg.setCustomContent(payContractNo);
			} else {
				String payContractNo = CFBSMsgUtil.rightFill(CFBSConstant.FILL_WORD_BLANK_SPACE, 60, "");
				pldsMsg.setCustomLength(payContractNo.length() + "");
				pldsMsg.setCustomContent(payContractNo);
			}

			int rdCount = 0;
			// 文件明细信息
			while (p_reqBat.readRecord()) {
				rdCount++;
				String outBank = this.getBankConfig().getMapAdvanceValuesExtra("outBankMapping", new String[]{"srcCode","srcArea"}, "value", new String[]{p_reqBat.readedDetail.getOppBankCode(),p_reqBat.readedDetail.getOppArea()});
				if(StringHelper.isNullOrEmpty(outBank)){
					outBank = this.getBankConfig().getMapAdvanceValue("outBankMapping", "srcCode", "value", p_reqBat.readedDetail.getOppBankCode());
				}
				if(StringHelper.isNullOrEmpty(outBank)){
					this.WriteBankLogLn(p_reqBat.readedDetail.getOppBankCode()+"-"+p_reqBat.readedDetail.getOppArea()+"映射不到清算行号");
				}
				if(rdCount == 1){//对方银行，取第一笔
					
					pldsMsg.setOutBank(outBank);
					//TranType("00504");//业务种类
					String keyTransTypeForMap = p_reqBat.reqHeader.transType;
					keyTransTypeForMap.replace("-ReSend", "");
					if("1908".equals(keyTransTypeForMap)||"6908".equals(keyTransTypeForMap)){
						keyTransTypeForMap = "1988";
					}
					String tmpTranType = this.getBankConfig().getMapValueBySrcXE("tranType"+keyTransTypeForMap, "srcCode", "desCode",p_reqBat.readedDetail.srcXElement,p_reqBat.useType);
					pldsMsg.setTranType(tmpTranType);
				}
				CfbsPlMsg.CfbsPlMsgDetail detail = pldsMsg.new CfbsPlMsgDetail();
				
				detail.setTxnSeq(p_reqBat.readedDetail.askNumber);
				detail.setEntrustDate(Format.Date8Format.format(p_reqBat.readedDetail.getPayDateTime()));
				//detail.setUserNo(p_reqBat.readedDetail.userCode);

                String userNo = p_reqBat.readedDetail.authCode;
                boolean useFixUserNo = getBankConfig().getValueAsBool("useFixUserNo");
                if (useFixUserNo) {
                    if ("1988".equalsIgnoreCase(p_reqBat.reqHeader.transType)) {
                        userNo = getBankConfig().getMapValueByKey("payUserIDMapping", p_reqBat.ownAct);
                        userNo = String.format("%-18s", userNo);// 用户编号
                    } else {
                        userNo = p_reqBat.readedDetail.sourceNoteCode;
                    }
                }

				detail.setUserNo(userNo);
				if (p_reqBat.reqHeader.isBatRec) {
					detail.setPayerAcc(p_reqBat.readedDetail.payAct);//付款人账号
					detail.setPayerName(p_reqBat.readedDetail.payName);//付款人名称
				} else if(p_reqBat.reqHeader.isBatPay){
					detail.setPayeeAcc(p_reqBat.readedDetail.recAct);//收款人账号
					detail.setPayeeName(p_reqBat.readedDetail.recName);//收款人名称
				}
				if (p_reqBat.reqHeader.isBatRec) {
					//01+5810+054516301+00600+付款行号前三位+付款帐号~
					//资金发的协议编号+付款行号前三位+付款帐号
					String outBankPre = "";
					if(outBank.length()>=3){
						outBankPre = outBank.substring(0,3);
					}
					String contractId = p_reqBat.readedDetail.contractNo+outBankPre+p_reqBat.readedDetail.payAct;
                    boolean useRecAuthCode = getBankConfig().getValueAsBool("useRecAuthCode");
                    WriteBankLogLn("单笔及批量代收合同协议号是否固定取AuthCode:"+useRecAuthCode);
                    if (useRecAuthCode) {
                        contractId = p_reqBat.readedDetail.authCode;
                    }
					detail.setContractId(contractId);//合同协议号
				}
				detail.setAmount(StringHelper.amountMultiply100(p_reqBat.readedDetail.payAmount));
				
				pldsMsg.getDetails().add(detail);
			}
			WriteBankLogLn2("批量代收付文件请求对象信息:\r\n" + JSONUtil.toJson(pldsMsg));
			
			String localFilePath = StringHelper.trimEnd(ftpLocalDirSend, File.separator) + File.separator;
			
			//将对象属性每个字段按接口文档要求的格式，形成明文文件
			String fileName = "";
			if (p_reqBat.reqHeader.isBatRec) {
				fileName = CfbsPlMsg.genReqPldsFile(pldsMsg, localFilePath);
			} else {
				fileName = CfbsPlMsg.genReqPldfFile(pldsMsg, localFilePath);
			}
			WriteBankLogLn("请求加密前明文文件路径：" + localFilePath + fileName);
			batInfo.reserve1 = localFilePath + fileName;
			
			CFBSMsgUtil.KEY = getEncryptKey();
			
			//将生成好的明文文件进行加密加压处理
			String encFileName = CFBSMsgUtil.fileEnc(localFilePath, fileName);
			WriteBankLogLn2("请求加密后密文文件路径：" + localFilePath + encFileName);
			
			batInfo.upFilePath = localFilePath + encFileName;
			batInfo.upFileState = "5";
			try{
				seqBatHelper.insertSeqBatchInfo(batInfo);
			}catch(Exception ex){
				this.WriteBankLogLn(ex);
				retAts.respInfo = "保存批次信息出现异常，不继续执行文件上传，异常信息："+LogHelper.getStackTraceFirstLine(ex);
				retAts.respCode = "0";
				retAts.transState = PaymentState.FAIL_Batch;
				retAts.payInfoCode = "E9999";
				retAts.writeRetToATS();
				return retAts;
			}
			
			//将加密后的文件发送到FTP
			FtpSet ftpSet = bankFront.getFtpSet("bat-upload");
			try{
				uploadFtpClient = FtpUtil.getConnectedClient(ftpSet.serverIP, ftpSet.port, ftpSet.userName, ftpSet.userPassword);
			}catch(Exception ex){
				this.WriteBankLogLn(ex);
				batInfo.upFileState = "3";
				seqBatHelper.updateUpFileState(batInfo);
				retAts.respInfo = "建立ftp连接失败："+LogHelper.getStackTraceFirstLine(ex);
				retAts.respCode = "0";
				retAts.transState = PaymentState.FAIL_Batch;
				retAts.payInfoCode = "E9999";
				retAts.writeRetToATS();
				return retAts;
			}
			boolean isCompleted = FtpUtil.upload(uploadFtpClient, localFilePath + encFileName, ftpSet.upDir + encFileName);
			
			retAts.respCode = "0";
            retAts.reqSeqID = p_reqBat.reqBatchNO;
            if (isCompleted) {
            	retAts.respInfo = "上传成功";
            	retAts.transState = "Uploaded";
            	retAts.payInfoCode = "I4001";
            	batInfo.upFileState = "2";
            	seqBatHelper.updateUpFileState(batInfo);
            } else {
            	retAts.respCode = "-1";
            	retAts.respInfo = "上传失败!";
            }
		} catch (Exception ex) {
			WriteBankLogLn(ex);
			retAts.respCode = "-1";
			retAts.respInfo = LogHelper.getStackTraceFirstLine(ex);
		} finally {
			if(seqBatHelper != null){
				seqBatHelper.close();
			}
			if (uploadFtpClient != null) {
				FtpUtil.disconnect(uploadFtpClient);
			}
		}

		retAts.writeRetToATS();
		return retAts;
	}
	
	public RetAtsQryBatPayRec d_QryBatPayRec(ReqQryBatPayRec p_reqQryBat) throws Exception {
		RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_reqQryBat.reqHeader);
		retAts.reqSeqID = p_reqQryBat.reqBatchNO;

		FTPClient ftpClient = null;
		SeqBatchInfoHelper seqBatHelper = null;
		try {
			
			seqBatHelper = new SeqBatchInfoHelper(p_reqQryBat.reqHeader.tenant, p_reqQryBat.getBgnDateTime());
			SeqBatchInfo batInfo = seqBatHelper.loadFromDb(p_reqQryBat.reqHeader.bankCode, p_reqQryBat.reqBatchNO);
		
			if(batInfo == null){
				retAts.respCode = "-1";
				retAts.respInfo = "查不到该批次的提交记录，请在未知状态下重发代收付指令";
				retAts.writeAfterDetail();
				return retAts;
			}
			
			WriteBankLogLn("批次"+p_reqQryBat.reqBatchNO+"对应的上传文件名为："+batInfo.upFileName);

			boolean isMatched = false;

			FtpSet ftpSet = bankFront.getFtpSet("bat-down");
			ftpClient = FtpUtil.getConnectedClient(ftpSet.serverIP, ftpSet.port, ftpSet.userName, ftpSet.userPassword);
			
			boolean isChangePath = ftpClient.changeWorkingDirectory(ftpSet.downDir);
			if(isChangePath) {
				String ftpLocalDirRec = getBankConfig().getValueAsFilePath("ftpLocalDirRec");
				File mdDir = new File(ftpLocalDirRec);
		        if (!mdDir.exists()) {
		            mdDir.mkdirs();
		        }
		        ftpLocalDirRec = StringHelper.trimEnd(ftpLocalDirRec, File.separator) + File.separator;
		        
				FTPFile[] files = ftpClient.listFiles();
				if (files == null || (files != null && files.length == 0)) {
					retAts.respCode = "-1";
					retAts.respInfo = "ftp服务器暂无结果文件";
					retAts.writeAfterDetail();
					return retAts;
				}
				
				for(FTPFile file : files) {
					boolean isDownload = FtpUtil.download(ftpClient, file.getName(), ftpLocalDirRec + file.getName());
					if(isDownload) {
						WriteBankLogLn("回应解密前文件名：" + file.getName());
						//将密文文件解密解压，decFileName为可读的明文文件名
						CFBSMsgUtil.KEY = getEncryptKey();
						String decFileName = CFBSMsgUtil.fileDec(ftpLocalDirRec, file.getName());
						WriteBankLogLn("回应解密后文件名：" + decFileName);
						if(StringHelper.isNullOrEmpty(decFileName)){
							WriteBankLogLn("解密"+ftpLocalDirRec + file.getName()+"后文件名为空");
							continue;
						}
						//按照交易类型分类，将明文文件解析成对象
						CfbsPlMsg plMsg = null;
						if(GZDSF01TransCode.BATREC.equals(decFileName.substring(10, 16))) {
							plMsg = CfbsPlMsg.procRespPldsFile(ftpLocalDirRec, decFileName);
						} else if(GZDSF01TransCode.BATPAY.equals(decFileName.substring(10, 16))){
							plMsg = CfbsPlMsg.procRespPldfFile(ftpLocalDirRec, decFileName);
						} else {
							continue;
						}
						String jsonMsg = JSONUtil.toJson(plMsg);
						WriteBankLogLn("批次响应结果数据：" + jsonMsg);
						if (plMsg.getRefFileName().contains(batInfo.upFileName)) {
							retAts.respCode = "0";
							isMatched = true;
							List<CfbsPlMsgDetail> plMsgDetailList = plMsg.getDetails();
							for (CfbsPlMsgDetail plMsgDetail : plMsgDetailList) {
								RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();
								
								if ("1998".equals(p_reqQryBat.reqHeader.transType)) {
									tmpRetDetail.recAct = plMsgDetail.getPayerAcc();
									tmpRetDetail.recName = plMsgDetail.getPayerName();
								} else {
									tmpRetDetail.payAct = plMsgDetail.getPayerAcc();
									tmpRetDetail.payName = plMsgDetail.getPayerName();
								}
								tmpRetDetail.postScript = plMsgDetail.getTxnSeq();
								tmpRetDetail.payAmount = StringHelper.amountDivide100(plMsgDetail.getAmount());
								tmpRetDetail.memo = plMsgDetail.getRemark().trim();
								tmpRetDetail.result = plMsgDetail.getRetCode();
								tmpRetDetail.payInfoCode = plMsgDetail.getRetCode();

								retAts.writeRetDetail(tmpRetDetail);
							}
							batInfo.downFileState = "2";
							batInfo.downFilePath = decFileName;
							if(seqBatHelper.updateDownFileStateAndPath(batInfo)==1){
								//处理成功后删除FTP文件，以免重复处理
								ftpClient.deleteFile(file.getName());
							}
						}
					}
				}
			}

			if (!isMatched) {
				retAts.respCode = "-1";
				retAts.respInfo = "未匹配到批次文件";
			}
		} catch (Exception ex) {
			retAts.respCode = "-1";
			retAts.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		} finally {
			if(seqBatHelper != null){
				seqBatHelper.close();
			}
			if (ftpClient != null) {
				FtpUtil.disconnect(ftpClient);
			}
		}

		retAts.writeAfterDetail();
		return retAts;
	}
}